package cn.com.nes.site.aspects;

import cn.com.nes.common.em.platform.PlatformEnum;
import cn.com.nes.common.util.JwtUtil;
import cn.com.nes.site.entity.UserInfo;
import cn.com.nes.site.entity.vo.BaseVO;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONReader;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Date;

import static org.springframework.web.context.request.RequestContextHolder.getRequestAttributes;

/**
 * 默认参数设置切面
 * 作用：为使用对象接收参数的接口，设置默认参数（从token中解析出来的用户信息）。
 */
@Slf4j
@Aspect
@Component
@Order(1)
public class DefaultRequestParamSettingAspect {

    public DefaultRequestParamSettingAspect() {
        log.debug("DefaultRequestParamSettingAspect Construct");
    }

    @Pointcut("execution(public * cn.com.nes.site.controller..*..*.*(..))")
    public void pointcut() {
    }

    /**
     * 接口处理之前，解析token，获取用户信息，为参数设置默认属性
     * @param joinPoint
     */
    @Before("pointcut()")
    public void settingCommonParamBeforeMethodInvoke(JoinPoint joinPoint) throws Exception {
        ServletRequestAttributes attributes = (ServletRequestAttributes) getRequestAttributes();
        if (attributes == null) {
            return;
        }
        final HttpServletRequest req = attributes.getRequest();
        // log.debug("请求入参设置用户属性切点 --> {}", req.getServletPath());
        String key = req.getHeader("key");
        if (StrUtil.isEmpty(key)) {
            return;
        }
        UserInfo userInfo = parsingTokenToObtainUserInfo(key);
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            if (arg instanceof BaseVO) {
                // 默认设置基础参数，platform为nes-agent
                ((BaseVO) arg).setOperateUserId(Long.parseLong(userInfo.getId()));
                ((BaseVO) arg).setOperateUserCompanyId(userInfo.getCompanyId());
                ((BaseVO) arg).setOperateUserCallCenterCompanyId(userInfo.getCallCenterCompanyId());
                ((BaseVO) arg).setOperateUserOpeCompanyId(userInfo.getNes_companyId());
                ((BaseVO) arg).setOperateUserCompanyType(userInfo.getCompanyType());
                ((BaseVO) arg).setOperateUserName(userInfo.getUsername());
                ((BaseVO) arg).setOperateNickName(userInfo.getNickname());
                ((BaseVO) arg).setOperateUserPhone(userInfo.getPhone());
                ((BaseVO) arg).setOperatePlatform(userInfo.getPlatform());
                ((BaseVO) arg).setOperateDate(new Date());
                ((BaseVO) arg).setUserInfo(userInfo);
                String traceId = StrUtil.isNotEmpty(req.getHeader("traceId")) ? req.getHeader("traceId") : (String) req.getAttribute("traceId");
                ((BaseVO) arg).setTraceId(traceId);

                if (PlatformEnum._easy_repair.getCode().equals(userInfo.getPlatform())) {
                    ((BaseVO) arg).setOperateUserId(Long.parseLong(userInfo.getId()));
                    ((BaseVO) arg).setOperateUserName(userInfo.getUsername());
                    ((BaseVO) arg).setOperateNickName(userInfo.getNickname());
                    ((BaseVO) arg).setOperateUserPhone(userInfo.getPhone());
                }

                if (StrUtil.isNotBlank(userInfo.getAreacode())) {
                    ((BaseVO) arg).getOperateUserAreaCodeSet().addAll(Arrays.asList(userInfo.getAreacode().split(";")));
                }
            }
        }
    }

    /**
     * 解析token，获得用户信息
     * @param token token
     * @return
     */
    private UserInfo parsingTokenToObtainUserInfo(String token) throws Exception {
        JwtUtil util = new JwtUtil();
        Claims c = util.parseJWT(token);// 注意：如果jwt已经过期了，这里会抛出jwt过期异常。
        String json = c.getSubject();
        UserInfo uinfo = JSON.parseObject(json, UserInfo.class, JSONReader.Feature.FieldBased);
        return uinfo;
    }

}
